package com.canaan.business.controller.pc.inOutStock;

import cn.hutool.core.util.StrUtil;
import com.canaan.business.common.enums.agv.AgvEnum;
import com.canaan.business.common.enums.inOutStock.BindTypeEnum;
import com.canaan.business.common.enums.storehouse.StorehouseStockStatusEnum;
import com.canaan.business.common.helper.EmptyStockHelper;
import com.canaan.business.domain.basic.WmsStorehouseLocation;
import com.canaan.business.domain.bill.Tray;
import com.canaan.business.domain.bill.TrayDetail;
import com.canaan.business.domain.inOutStock.BindRecord;
import com.canaan.business.domain.storehouse.StockStage;
import com.canaan.business.domain.storehouse.WmsStorehouseStock;
import com.canaan.business.domain.vo.EmptyTrayVo;
import com.canaan.business.domain.vo.OutStockQueryVo;
import com.canaan.business.domain.vo.WmsStorehouseStockVo;
import com.canaan.business.service.agv.IAgvTaskDispatchService;
import com.canaan.business.service.basic.IWmsStorehouseLocationService;
import com.canaan.business.service.bill.ITrayDetailService;
import com.canaan.business.service.bill.ITrayService;
import com.canaan.business.service.inOutStock.IBindRecordService;
import com.canaan.business.service.storehouse.IWmsStorehouseStockService;
import com.canaan.common.annotation.Log;
import com.canaan.common.core.controller.BaseController;
import com.canaan.common.core.domain.AjaxResult;
import com.canaan.common.core.redis.RedisCache;
import com.canaan.common.enums.BusinessType;
import com.canaan.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Api(tags = "空托盘")
@RestController
@RequestMapping("/inOutStock/emptyTray")
public class EmptyTrayController extends BaseController {
    @Resource
    private ITrayService trayService;
    @Resource
    private IWmsStorehouseLocationService storehouseLocationService;
    @Resource
    private IWmsStorehouseStockService storehouseStockService;
    @Resource
    private IBindRecordService bindRecordService;
    @Resource
    private ITrayDetailService trayDetailService;
    @Resource
    private IAgvTaskDispatchService agvTaskDispatchService;
    @Resource
    private RedisCache redisCache;
    @Resource
    EmptyStockHelper emptyStockHelper;
    @ApiOperation(value = "空托盘组入库")
    @Log(title = "空托盘线入库", businessType = BusinessType.INSERT)
    @PostMapping("/putWay")
    @Transactional
    public AjaxResult putWay(@RequestBody EmptyTrayVo emptyTrayVo) {
        if(StringUtils.isEmpty(emptyTrayVo.getLocationNo())){
            return error("库位为空");
        }
        if(StringUtils.isEmpty(emptyTrayVo.getTrayNo())){
            return error("托盘号为空");
        }
        if(StringUtils.isEmpty(emptyTrayVo.getShelfNo())){
            return error("料架号为空");
        }
        if(StringUtils.isEmpty(emptyTrayVo.getProductNo())){
            return error("物料号为空");
        }
        WmsStorehouseLocation sourceLocation=storehouseLocationService.selectWmsStorehouseLocationByNo(emptyTrayVo.getLocationNo());
        if(sourceLocation==null){
            return error("库位"+emptyTrayVo.getLocationNo()+"数据不存在");
        }
        WmsStorehouseStock sourceStock=storehouseStockService.selectWmsStorehouseStockByLocationNo(emptyTrayVo.getLocationNo());
        if(sourceStock==null){
            return error("库位"+emptyTrayVo.getLocationNo()+"库存数据不存在");
        }
        if(!StorehouseStockStatusEnum.NORMAL.getCode().equals(sourceStock.getStatus())){
            return error("库位"+emptyTrayVo.getLocationNo()+"状态不是NORMAL");
        }
        if(StringUtils.isNotEmpty(sourceStock.getContainerNo())){
            return error("库位"+emptyTrayVo.getLocationNo()+"已经存在容器");
        }
        if(StringUtils.isNotEmpty(sourceStock.getTrayNo())){
            return error("库位"+emptyTrayVo.getLocationNo()+"已经存在托盘");
        }
        //根据料架判断收已经存在库存
        WmsStorehouseStock shelfStockQuery =new WmsStorehouseStock();
        shelfStockQuery.setContainerNo(emptyTrayVo.getShelfNo());
        shelfStockQuery.setDelFlag("0");
        List<WmsStorehouseStock> shelfStocks=storehouseStockService.selectWmsStorehouseStockList(shelfStockQuery);
        if(shelfStocks!=null&&shelfStocks.size()>1){
            //判断绑定点位是否和当前库存点位一致
            if(!StrUtil.equalsIgnoreCase(shelfStocks.get(0).getStorehouseLocationNo(),emptyTrayVo.getLocationNo())){
                return error("料架"+ emptyTrayVo.getShelfNo()+"存在库位"+shelfStocks.get(0).getStorehouseLocationNo());
            }
            String collect = shelfStocks.stream().map(WmsStorehouseStock::getStorehouseLocationNo).collect(Collectors.joining(", "));
            return error( "料架"+ emptyTrayVo.getShelfNo()+"存在多库位中"+collect);
        }
        //根据托盘判断是否已经存在库存
        WmsStorehouseStock trayQuery=new WmsStorehouseStock();
        trayQuery.setTrayNo(emptyTrayVo.getTrayNo());
        trayQuery.setDelFlag("0");
        List<WmsStorehouseStock> trayStocks=storehouseStockService.selectWmsStorehouseStockList(trayQuery);
        if(trayStocks!=null&&trayStocks.size()!=0){
            return error("托盘"+emptyTrayVo.getTrayNo()+"存在库位"+shelfStocks.get(0).getStorehouseLocationNo());
        }
        BindRecord shelfQuery = new BindRecord();
        shelfQuery.setBindType((long) BindTypeEnum.SHELF_TRAY.getCode());
        shelfQuery.setParentNo(emptyTrayVo.getShelfNo());
        shelfQuery.setDelFlag("0");
        List<BindRecord> shelfRecordList = bindRecordService.selectBindRecordList(shelfQuery);
        if (shelfRecordList != null && shelfRecordList.size() != 0) {
            BindRecord bindRecord=shelfRecordList.get(0);
            if(!emptyTrayVo.getShelfNo().equals(bindRecord.getParentNo())) {
                return error(emptyTrayVo.getShelfNo() + "已经存在绑定数据");
            }
        }
        BindRecord trayStockQuery = new BindRecord();
        trayStockQuery.setBindType((long) BindTypeEnum.SHELF_TRAY.getCode());
        trayStockQuery.setChildNo(emptyTrayVo.getTrayNo());
        trayStockQuery.setDelFlag("0");
        List<BindRecord> trayRecordList = bindRecordService.selectBindRecordList(trayStockQuery);
        if (trayRecordList != null && trayRecordList.size() != 0) {
            return error(emptyTrayVo.getTrayNo() + "已经存在绑定数据");
        }

        String key = "IN_LOCK";

        //TODO 临时方案锁，后期处理
        String lock = redisCache.getCacheObject(key);
        if (StringUtils.equals(lock, "true")) {
            throw new RuntimeException("有任务正在进行中，请稍后再试");
        }
        redisCache.setCacheObject(key, "true");
        try {
            putWayLock(emptyTrayVo,sourceStock,sourceLocation);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            //TODO 临时方案
            redisCache.setCacheObject(key, "false");
        }

        return toAjax(1);
    }

    /**
     * 入空托盘组锁逻辑
     */
    private void putWayLock(EmptyTrayVo emptyTrayVo,WmsStorehouseStock sourceStock,WmsStorehouseLocation sourceLocation){
        Tray tray=trayService.selectTrayByTrayNo(emptyTrayVo.getTrayNo());
        if(tray==null){
            tray=new Tray();
            tray.setTrayNo(emptyTrayVo.getTrayNo());
            trayService.insertTray(tray);
        }
        else{
            trayDetailService.deleteTrayDetailByTrayNo(emptyTrayVo.getTrayNo());
        }
        TrayDetail trayDetail=new TrayDetail();
        trayDetail.setTrayNo(emptyTrayVo.getTrayNo());
        trayDetail.setProductNo(emptyTrayVo.getProductNo());
        trayDetail.setProductName("空托盘");
        trayDetailService.insertTrayDetail(trayDetail);

        //添加绑定关系
        BindRecord bindRecord = new BindRecord();
        bindRecord.setParentNo(emptyTrayVo.getShelfNo());
        bindRecord.setChildNo(emptyTrayVo.getTrayNo());
        bindRecord.setBindType((long) BindTypeEnum.SHELF_TRAY.getCode());
        bindRecordService.insertBindRecord(bindRecord);

        WmsStorehouseLocation destLocation =emptyStockHelper.analyseInStock("", emptyTrayVo.getProductNo(), true,false);
        WmsStorehouseStock destStock=storehouseStockService.selectWmsStorehouseStockByLocationNo(destLocation.getNo());
        if(destStock==null){
            throw new RuntimeException("目标库位"+destLocation.getNo()+"库存数据不存在");
        }
        sourceStock.setContainerNo(emptyTrayVo.getShelfNo());
        sourceStock.setTrayNo(emptyTrayVo.getTrayNo());
        sourceStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
        storehouseStockService.updateWmsStorehouseStock(sourceStock);
        destStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
        storehouseStockService.updateWmsStorehouseStock(destStock);

        agvTaskDispatchService.createTaskDispatch("",sourceLocation, destLocation, AgvEnum.TASK_TYPE.IN_EMPTY_TRAYS,
                emptyTrayVo.getShelfNo(),emptyTrayVo.getTrayNo());
    }

    @ApiOperation(value = "空托盘组出库")
    @Log(title = "空托盘组出库", businessType = BusinessType.INSERT)
    @PostMapping("/outStock")
    @Transactional
    public AjaxResult outStock(@RequestBody EmptyTrayVo emptyTrayVo) {
        if(StringUtils.isEmpty(emptyTrayVo.getProductNo())){
            return error("物料号为空");
        }
        String key = "OUT_LOCK";

        //TODO 临时方案锁，后期处理
        String lock = redisCache.getCacheObject(key);
        if (StringUtils.equals(lock, "true")) {
            throw new RuntimeException("有上架任务正在进行中，请稍后再试");
        }
        redisCache.setCacheObject(key, "true");
        try {
            outStockLock(emptyTrayVo.getProductNo());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            //TODO 临时方案
            redisCache.setCacheObject(key, "false");
        }
        return toAjax(1);
    }

    /**
     * 空托盘出库逻辑
     */
    private void  outStockLock(String productNo){
        List<String> productNos =new ArrayList<>();
        productNos.add(productNo);
        OutStockQueryVo outStockQueryVo=new OutStockQueryVo();
        outStockQueryVo.setProductNos(productNos);
        List<WmsStorehouseStockVo> stockVos=storehouseStockService.selectWmsStorehouseStockListByProductNos(outStockQueryVo);
        if(stockVos==null||stockVos.size()==0){
            throw new RuntimeException("空托盘组库存不足");
        }
        WmsStorehouseStockVo sourceStockVo=stockVos.get(0);
        WmsStorehouseStock sourceStock=storehouseStockService.selectWmsStorehouseStockByLocationNo(sourceStockVo.getStorehouseLocationNo());
        WmsStorehouseLocation sourceLocation=storehouseLocationService.selectWmsStorehouseLocationByNo(sourceStockVo.getStorehouseLocationNo());
        List<WmsStorehouseStockVo> outStockVos=storehouseStockService.selectEmpWmsStorehouseOutStockList();
        if(outStockVos==null||outStockVos.size()==0){
            throw new RuntimeException("不存在空的出库接驳位");
        }
        WmsStorehouseStockVo destStockVo=outStockVos.get(0);
        WmsStorehouseStock destStock=storehouseStockService.selectWmsStorehouseStockByLocationNo(destStockVo.getStorehouseLocationNo());
        WmsStorehouseLocation destLocation=storehouseLocationService.selectWmsStorehouseLocationByNo(destStockVo.getStorehouseLocationNo());
        sourceStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
        storehouseStockService.updateWmsStorehouseStock(sourceStock);
        destStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
        storehouseStockService.updateWmsStorehouseStock(destStock);
        //生成AGV任务
        agvTaskDispatchService.createTaskDispatch("",sourceLocation, destLocation, AgvEnum.TASK_TYPE.OUT_EMPTY_TRAYS,
                sourceStock.getContainerNo(),sourceStock.getTrayNo());
    }
}
